home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pas_0493.zip / RODENT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-04-15  |  6KB  |  195 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 115 of 150
  3. From : Sean Palmer                         1:104/123.0          08 Apr 93  15:35
  4. To   : All
  5. Subj : G:Rodent unit
  6. ────────────────────────────────────────────────────────────────────────────────}
  7. { Rodent unit  v1.1      OooO }
  8. {   03/28/93              \/  }
  9. { Interrupt-style interface for Microsoft mouse, Turbo Pascal 6.0}
  10. { Copyright (c) 1993 Sean L. Palmer }
  11. { Released to the Public Domain }
  12.  
  13. { You may distribute this freely and incorporate it with no royalties. }
  14. { Please credit me if your program uses these routines! }
  15. { If you really like them or learn something neat from me then I'd }
  16. { appreciate a small ($1 to $5) donation. }
  17. { Or contact me if you need something programmed or like my work... }
  18. { I probably have the wierdest indenting style for pascal ever! 8)  }
  19. { And, by God my stuff is optimized!! }
  20.  
  21. { Sean L. Palmer (aka Ghost)}
  22. { 2237 Lincoln St. }
  23. { Longmont, CO 80501 }
  24. { (303) 651-7862 }
  25. { also on FIDO, or at palmers@spot.colorado.edu }
  26.  
  27. unit Rodent;
  28. {$A-,B-,D-,E-,F-,G+,I-,L-,N-,O-,R-,S-,V-,X+}
  29. {make sure you alloc enough stack space in main program!}
  30. {as written, requires a 286+ and that the mouse exists}
  31. interface
  32.  
  33. const
  34.  x:integer=0; y:integer=0;   {current mouse pos}
  35.  xs:integer=0; ys:integer=0; {mickey counts (unreliable)}
  36.  left=1; center=2; right=4;  {button masks:(btn and left)<>0 if left button
  37. down}
  38.  b:boolean=false;            {button status, true if any button down}
  39. var
  40.  btn:byte absolute b;
  41.  hidden:boolean;
  42. type
  43.  pMouseHook=^tMouseHook;
  44.  tMouseHook=procedure;
  45.  
  46. {avoid calling dos, bios, and mouse routines from these if possible}
  47. function erasHook(h:tMouseHook):pMouseHook;
  48. function moveHook(h:tMouseHook):pMouseHook;
  49. function drawHook(h:tMouseHook):pMouseHook; {change out handlers}
  50. function clikHook(h:tMouseHook):pMouseHook;
  51. function liftHook(h:tMouseHook):pMouseHook;
  52.  
  53. procedure show(f:boolean);          {true=show}
  54. procedure confine(l,t,r,b:integer); {set min,max bounds}
  55. procedure moveTo(h,v:integer);
  56. procedure setSpeed(xs,ys,thr:word); {set x,y pix per 16 mickeys, double speed
  57. threshold}
  58.  
  59. implementation
  60.  
  61. {This unit should work in any mode, but you need to provide the routines
  62.  to draw and erase the cursor.}
  63. {note: reason coords are scaled *16 throughout is because mouse driver}
  64.  {stupidly messes with the values differently in different modes.}
  65.  {This is just a work-around.}
  66. {PS: don't trust mickey counts in DI & SI in event handler.}
  67.  {I found that they are extremely inaccurate, so I left them out.}
  68. {You could use my Ticker unit to access clock ticks to time double clicks!}
  69.  
  70. var
  71.  hideCount:byte absolute hidden;
  72.  
  73. procedure defaultMouseHook;far;assembler;asm end;
  74.  
  75. procedure cli;inline($FA);
  76. procedure sti;inline($FB);
  77.  
  78. const
  79.  vDrawHook:tMouseHook=defaultMouseHook;
  80.  vErasHook:tMouseHook=defaultMouseHook;
  81.  vMoveHook:tMouseHook=defaultMouseHook;
  82.  vClikHook:tMouseHook=defaultMouseHook;
  83.  vLiftHook:tMouseHook=defaultMouseHook;
  84.  
  85. function drawHook(h:tMouseHook):pMouseHook;begin drawHook:=@vDrawHook; cli;
  86. vDrawHook:=h; sti; end;
  87. function erasHook(h:tMouseHook):pMouseHook;begin erasHook:=@vErasHook; cli;
  88. vErasHook:=h; sti; end;
  89. function moveHook(h:tMouseHook):pMouseHook;begin moveHook:=@vMoveHook; cli;
  90. vMoveHook:=h; sti; end;
  91. function clikHook(h:tMouseHook):pMouseHook;begin clikHook:=@vClikHook; cli;
  92. vClikHook:=h; sti; end;
  93. function liftHook(h:tMouseHook):pMouseHook;begin liftHook:=@vLiftHook; cli;
  94. vLiftHook:=h; sti; end;
  95.  
  96. {calling regs:}
  97.  {ax:triggering event bit mask}
  98.  {bx:button status bit mask (bit 0=left,1=center,2=right)}
  99.  {cx:mouse X/bit 7 is sign for di,bit 0 always=0}
  100.  {dx:mouse Y/bit 7 is sign for si}
  101.  {di:abs mouse Delta X}
  102.  {si:abs mouse Delta Y}
  103.  
  104. {bits in event mask:}
  105.  {0:move}
  106.  {1:left btn down}
  107.  {2:left btn up}
  108.  {3,4:center btn}
  109.  {5,6:right btn}
  110.  
  111. {This code is real easy to break, be careful!}
  112. procedure doMouseHook;far;assembler;asm
  113.  cli;
  114.  push ax; mov ax,seg @DATA; mov ds,ax; pop ax;
  115.  mov xs,si; mov ys,di; {disregard di,si mickey counts}
  116.  mov btn,bl;
  117.  and cx,$3FFF; shr cx,3; and dx,$3FFF; shr dx,3; {strip hi bits}
  118.  push ax; push cx; push dx;  {save event status}
  119.  test hidden,$FF; jnz @NOERAS; call vErasHook; @NOERAS:
  120.  pop dx; mov y,dx; pop cx; mov x,cx;
  121.  call vMoveHook;  {always assume mouse has moved, disregard bit 0 of ax}
  122.  test hidden,$FF; jnz @NODRAW; call vDrawHook; @NODRAW:
  123.  pop ax; {restore event status}
  124. @CLIK: test al,00101010b; jz @LIFT; {check any button clik flag}
  125.  push ax; call vClikHook; pop ax;
  126. @LIFT: test al,01010100b; jz @EXIT; {check any button lift flag}
  127.  call vLiftHook;
  128. @EXIT: sti;
  129.  end;
  130.  
  131. procedure show(f:boolean);begin
  132.  cli;
  133.  if f then begin
  134.   if hidden then begin dec(hideCount); if not hidden then vDrawHook; end;
  135.   end
  136.  else begin if not hidden then vErasHook; inc(hideCount); end;
  137.  sti;
  138.  end;
  139.  
  140. Procedure confine(l,t,r,b:integer);assembler;asm
  141.  mov ax,7; mov cx,l; shl cx,3; mov dx,r; shl dx,3; int $33;
  142.  mov ax,8; mov cx,t; shl cx,3; mov dx,b; shl dx,3; int $33;
  143.  end;
  144.  
  145. procedure moveTo(h,v:integer);begin
  146.  if not hidden then vErasHook;
  147.  asm mov cx,h; mov x,cx; shl cx,3;
  148.      mov dx,v; mov y,dx; shl dx,3;
  149.      mov ax,4; int $33; end;
  150.  if not hidden then vDrawHook;
  151.  end;
  152.  
  153. procedure setSpeed(xs,ys,thr:word);assembler;asm
  154.  mov ax,$1A; mov bx,xs; shl bx,3; mov cx,ys; shl cx,3; mov dx,thr; int $33;
  155.  end;
  156.  
  157. var
  158.  oldMouseHook:pointer;
  159.  oldEventMask:word;
  160.  
  161. procedure removeMouse;begin
  162.  if not hidden then show(false);
  163.  asm les dx,oldMouseHook; mov cx,oldEventMask; mov ax,$C; int $33;end;
  164.  end;
  165.  
  166. var
  167.  mouseHook:pointer absolute 0:$33*4;
  168. const
  169.  eventMask=$7F;  {all events}
  170.  
  171. function exists:boolean;assembler;asm
  172.  xor ax,ax; mov es,ax; mov bx,es:[$33*4]; or bx,es:[$33*4+2]; jz @X; {no}
  173.  xor ax,ax; int $33; @X:  {result in al}
  174.  end;
  175.  
  176. begin
  177.  if exists then begin
  178.   setSpeed(32,64,4);    {set up a natural-feeling speed for 640x480}
  179.   moveTo(0,0);confine(0,0,0,0); {trap the little sucker}
  180.   hideCount:=1;
  181.   asm
  182.    push cs;
  183.    pop es;
  184.    mov dx,offset doMouseHook;
  185.    mov cx,eventMask;
  186.    mov ax,$14;
  187.    int $33;
  188.    mov oldEventMask,cx;
  189.    mov word ptr oldMouseHook,dx;
  190.    mov word ptr oldMouseHook+2,es;
  191.    end;
  192.   end
  193.  else begin writeln('Need mouse.'); halt(1);end;
  194.  end.
  195.